package org.example.platform.beans.factory;


import cn.hutool.core.bean.BeanUtil;
import lombok.Data;

import java.lang.reflect.Constructor;

/**
 * 实例化Bean类
 */
@Data
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory {
    private InstantiationStrategy instantiate = (InstantiationStrategy) new CglibSubclassingInstantiationStrategy();

    @Override
    protected BeanDefinition getBeanDefinition(String beanName) throws Exception {
        return null;
    }

//    @Override
//    Object createBean(String beanName, BeanDefinition beanDefinition) throws Exception {
//        Object bean = null;
//        try {
//            bean = createBeanInstance(beanName, beanDefinition);
//            // 给 Bean 填充属性
//            applyPropertyValues(beanName, bean, beanDefinition);
//        } catch (Exception e) {
//            throw new Exception(e);
//        }
//        addSingleton(beanName, bean);
//        return bean;
//    }

    @Override
    protected Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args) throws Exception {
        Object bean = null;
        try {
            bean = createBeanInstance(beanName, beanDefinition, args);
            // 给 Bean 填充属性
            applyPropertyValues(beanName, bean, beanDefinition);
        } catch (Exception e) {
            throw new Exception(e);
        }
        addSingleton(beanName, bean);
        return bean;
    }

//    Object createBeanInstance(String beanName, BeanDefinition beanDefinition) throws Exception {
//        Object bean = null;
//        try {
//            bean = beanDefinition.getBean().newInstance();
//        } catch (Exception e) {
//            throw new Exception(e);
//        }
//        addSingleton(beanName, bean);
//        return bean;
//    }

    Object createBeanInstance(String beanName, BeanDefinition beanDefinition, Object[] args) throws Exception {
        Constructor constructor = null;
        Class<?> beanClass = beanDefinition.getBean();
        Constructor<?>[] dec = beanClass.getDeclaredConstructors();
        for (Constructor ctor : dec) {
            if (null != args && args.length == ctor.getParameterTypes().length) {
                constructor = ctor;
                break;
            }
        }
        return getInstantiate().instantiate(beanDefinition, beanName, constructor, args);
    }


    /**
     * 属性填充
     */
    void applyPropertyValues(String beanName, Object bean, BeanDefinition beanDefinition) throws Exception {
        try {
            PropertyValues propertyValues = beanDefinition.getPropertyValues();
            for (PropertyValue propertyValue : propertyValues.getPropertyValues()) {
                String name = propertyValue.getName();
                Object value = propertyValue.getValue();
                if (value instanceof BeanReference) {
                    // A依赖B ，获取B的实例化
                    BeanReference beanReference = (BeanReference) value;
                    value = getBean(beanReference.getBeanName());
                }

                // 属性填充
                BeanUtil.setFieldValue(bean, name, value);
            }
        } catch (Exception e) {
            throw new Exception(beanName);
        }
    }


}
